#ifndef car_H
#define car_H

#include <QGraphicsItem>
#include <QSet>
#include "types.h"

class QRoundabout;
class QPixmap;
class QPointF;
class QTimer;
class Barrier;

class Car : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)

public:
    Car(QPointF pos, qreal angle, qreal laneWidth, QRoundabout *r, int lane, short int dest, int source, short int destLane, int rules);
    ~Car();
    QRectF boundingRect() const; //funkcja wirtualna. Całe rysowanie wenątrz tego prostokąta
    QPainterPath shape() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget); //aktualne rysowanie. Także wirtualna.

private:
    Barrier* collidesWithBarrier(BarrierType type);
    bool collidesWithLine(QLineF);
    void orbit(qreal radius, bool accelerate = true);
    void enterRoundabout();
    qreal computeAngle();
    bool turnExit();
    bool turnExitShortcut();
    void brake();
    bool changeLane(); //zwraca 1 jeśli zakończono zmiane pasa
    qreal goForward();
    void prepareStopLine(double, Barrier*);
    void createChangeLaneDangerZone();
    void createZebraDangerZone(int nrBranch, int nrLane);
    void createShortcutEndDangerZone(int);
    Barrier* findOutletBarrier(int);
    void removeIgnoredCars(QList<QGraphicsItem*> *);

    // rules:
    void official();
    void matchingLanes();
    void invertedPriority();

protected:
    void advance(int step);
    void mousePressEvent ( QGraphicsSceneMouseEvent * event );
    void hoverEnterEvent ( QGraphicsSceneHoverEvent * event );

private:
    /** \name Stałe
      * Stałe wartości opisujące podróż samochodu.
      */
    //@{
    const qreal _size;        ///< wyznacza krótszy bok i połowę dłuższego
    const int _rules;             ///< Identyfikator zasad. Numerom 0, 1, 2 odpowiadają zasady official(), matchingLanes() i invertedPriority().
    const short int _destination; ///< Numer gałęzi docelowej.
    const short int _source;      ///< Numer źródłowej gałęzi.
    const short int _destLane;    ///< Numer pasa na docelowej gałęzi.
    //@}
    qreal _angle;       ///< Kąt odchylenia. Początkowo w stopniach, potem, podczas jazdy na obręczy - w radianach.
    qreal _speed;       ///< Aktualna prędkość. O tyle pikseli zostanie przesunięty samochód podczas jazdy do przodu na gałęzi.
    qreal _minSpeed;    ///< minimalna prędkość do której może zahamować wóz (powiązane z irytacją)
    qreal _laneShift;   ///< Przesunięcie prostopadłe do kierunku jazdy. Ma wartość niezerową tylko podczas zmiany pasa.
    qreal _maxSpeed;        ///< Maksymalna prędkość jaką może rozwinąć samochód.
    QPainterPath *_dangerZone;  ///< Strefa zagrożenia. Samochód nie pojedzie, dopóki coś (widocznego) będzie znajdowało się w tej strefie.
    QTimer *_irritationTimer;   ///< Timer sprzężony z irritationTick(). Jest uruchamiany dopiero, gdy samochód zbyt długo będzie się nie poruszał.
    int _secondsOfIrritation;   ///< Ilość sekund irytacji kierowcy. \see irritationTick()
    short int _lane;        ///< Numer pasa, na którym aktualnie znajduje się samochód. 0 to najbardziej prawy (zawenętrzny) pas.
    bool _onBranch;         ///< Prawda, jeżeli samochód jest na gałęzi ronda. Musi być zawsze przeciwne do _onRim.
    bool _onRim;            ///< Prawda, jeżeli samochód jest na obręczy ronda. Musi być zawsze przeciwne do _onBranch.
    Manouver _state;        ///< Aktualny stan samochodu.
    bool _disabled;         ///< Samochód może zostać zatrzymany przez użytkownika. Przez prawokliknięci ustawiana jest ta flaga, która blokuje animację oraz przekreśla samochód.
    Barrier *_destBarrier;  ///< Bariera zjazdu z ronda powiązana z gałęzią docelową jest na tyle ważna, że jej adres wyszukujemy w konstruktorze. Nie musimy przez to powtarzać tej operacji w advance(), wystarczy szybkie porównanie.
    bool _shortcutUsed;     ///< Użycie skrótu nieco upraszcza sprawę poruszania się po rondzie; ta flaga pozwala nam zastąpić domyślny zjazd z ronda nieco prostszym.
    bool _zebraDangerZone;  ///< Ta flaga, jeśli ustawiona, oznajmia, że aktualna strefa zagrożenia jest przeznaczona dla pieszych. Innymi słowy, tylko piesi mogą nas zatrzymać.
    QSet<Car*> _ignoredCars;  ///< Lista samochodów, które będą ignorowane przy wykrywaniu kolizji
    Barrier* _lastBarrier;
    bool _destinationReached;

    QColor _color;          ///< Kolor samochodu jest ustalany w konstruktorze i zależy od wybranych zasad.
    QRoundabout *_qr;
    QRectF *_car;           ///< Prostokątna "rama" samochodu. Służy do zapewnienia boundingRect() oraz shape().

    /** \name Rogi pojazdu
      *  Zmienne upperLeft, upperRight, bottomRight, bottomLeft to współrzędne kątów samochodu i są wyliczane w konstruktorze. Służą później do szybszego sprawdzania kolizji w funkcji collidesWithLine(QPointF).
      */
    //@{
    QPointF upperLeft;
    QPointF upperRight;
    QPointF bottomRight;
    QPointF bottomLeft;
    //@}

    QPainterPath *_stopLine;    ///< Linia zatrzymania. Gdy samochód chce wjechać, lub zjechać z ronda, najpierw dojeżdża do tej linii, a dopiero wtedy zacznie skręcać.

    bool debugVar;

signals:
    void iAmDestroyed();

private slots:
    void irritationTick();
};

#endif
